package exploits

import (
	"encoding/binary"
	"encoding/hex"
	"net"
	"prismx_cli/core/models"
	"prismx_cli/utils/netUtils"
	"strconv"
	"time"
)

// init 注册插件插件
func init() {
	var (
		negotiateProtocolRequest, _ = hex.DecodeString("00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200")
		sessionSetupRequest, _      = hex.DecodeString("00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000")
		treeConnectRequest, _       = hex.DecodeString("00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00")
		transNamedPipeRequest, _    = hex.DecodeString("0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00")
	)

	models.Register(models.AppVulInfo{
		App:   "microsoft-ds",
		Query: "app:\"microsoft-ds\"",
		Meta: models.VulMeta{
			Name:        "MS17-010 (Eternal blue)",
			Tags:        []string{"RCE"},
			Author:      "一曲成殇",
			Description: "永恒之蓝(EternalBlue)是由美国国家安全局开发的漏洞利用程序,对应微软漏洞编号ms17-010。该漏洞利用工具由一个名为”影子经济人”（Shadow Brokers）的神秘黑客组织于2017年4月14日公开的利用工具之一，该漏洞利用工具针对TCP 445端口(Server Message Block/SMB)的文件分享协议进行攻击，攻击成功后将被用来传播病毒木马。由于利用永恒之蓝漏洞利用工具进行传播病毒木马事件多，影响特大，因此很多时候默认将ms17-010漏洞称为“永恒之蓝”。",
			Homepage:    "https://microsoft.com",
			Level:       5,
			References:  "https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-0796",
			Solution:    "关闭445端口、打开防火墙、安装安全软件、安装对应补丁。",
			CreateAt:    "2021-12-07",
			Available:   false,
			Steps: models.StepsMeta{VerifySteps: models.VerifySteps{VerifyGo: func(scheme, ip string, port int, duration time.Duration) (result models.VulResult) {

				conn, err := netUtils.SendDialTimeout("tcp", net.JoinHostPort(ip, strconv.Itoa(port)), duration)
				if err != nil {
					return
				}
				defer conn.Close()
				if err = conn.SetDeadline(time.Now().Add(duration)); err != nil {
					return
				}
				if _, err = conn.Write(negotiateProtocolRequest); err != nil {
					return
				}
				reply := make([]byte, 1024)
				if n, err := conn.Read(reply); err != nil || n < 36 {
					return
				}
				if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
					return
				}

				if _, err = conn.Write(sessionSetupRequest); err != nil {
					return
				}
				n, err := conn.Read(reply)
				if err != nil || n < 36 {
					return
				}

				if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
					return
				}

				userID := reply[32:34]
				treeConnectRequest[32] = userID[0]
				treeConnectRequest[33] = userID[1]
				_, err = conn.Write(treeConnectRequest)
				if err != nil {
					return
				}
				if n, err := conn.Read(reply); err != nil || n < 36 {
					return
				}

				treeID := reply[28:30]
				transNamedPipeRequest[28] = treeID[0]
				transNamedPipeRequest[29] = treeID[1]
				transNamedPipeRequest[32] = userID[0]
				transNamedPipeRequest[33] = userID[1]

				_, err = conn.Write(transNamedPipeRequest)
				if err != nil {
					return
				}
				if n, err := conn.Read(reply); err != nil || n < 36 {
					return
				}
				if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
					result.State = true
					result.Response = string(reply)
					result.Request = string(transNamedPipeRequest)
				}
				return result
			}}},
		},
	})
}
